Spring 使用简单Demo进行源码调试(四)

版权声明:本文为博主原创文章,转载请注明出处,谢谢!

版权声明:本文为博主原创文章,转载请注明出处:http://blog.jerkybible.com/2015/05/11/Spring 使用简单Demo进行源码调试(四)/

访问原文「Spring 使用简单Demo进行源码调试(四)

接上篇日志Spring 使用简单Demo进行源码调试(三)继续。

第一步
展开loadBeanDefinitions(resources)。这个代码比较简单,是对每一个资源进行加载。

1
2
3
4
5
6
7
8
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource);
}
return counter;
}

展开loadBeanDefinitions(resource)。这一步为从特定的XML文件中加载bean factory,使用EncodedResource包装传来的resource,然后进一步加载。EncodedResource结合特定编码的资源描述符或特定字符集用于阅读资源,这里的资源描述符和特定字符集都为。

1
2
3
4
5
/**
* 从特定的XML文件中加载bean factory
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}

第二步
展开 loadBeanDefinitions(new EncodedResource(resource));。这一步从encodedResource获取读入流,然后设置编码,最后通过doLoadBeanDefinitions(inputSource, encodedResource.getResource())进一步解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* 从特定的XML文件中加载bean factory
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

第三步
展开doLoadBeanDefinitions(inputSource, encodedResource.getResource())。这一步初始化Document实例,然后通过registerBeanDefinitions(doc, resource)注册bean定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 实际的从特定的XML文件中加载bean factory
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}

第四步
展开registerBeanDefinitions(doc, resource)。这一步比较好理解,直接看documentReader.registerBeanDefinitions(doc, createReaderContext(resource))。

1
2
3
4
5
6
7
8
9
10
11
/**
* 使用DOM document注册bean定义.
*/
@SuppressWarnings("deprecation")
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}

第五步
展开documentReader.registerBeanDefinitions(doc, createReaderContext(resource))。还是比较简单,哎,看doRegisterBeanDefinitions(root)这一步吧。

1
2
3
4
5
6
7
8
9
/**
* 使用"spring-beans" XSD 或者 DTD 解析bean定义
*/
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}

第六步
展开doRegisterBeanDefinitions(root)。这一步使用Doc里的root元素注册每一个bean定义。使用createDelegate的原因是任何嵌套的< bean>元素将导致该方法递归。为了传播和保存 default-*属性正确,跟踪当前的(parent)delegate,这可能是null。为了后退创建一个引用到父delegate新的(child)delegate,最终重置delegate改回到原来(parent)引用。这种行为模拟一堆delegate,并不需要专门得类完成。最后通过预处理xml、解析bean定义和后处理xml完成注册bean定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Register each bean definition within the given root {@code &lt;beans/&gt;} element.
*/
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getEnvironment().acceptsProfiles(specifiedProfiles)) {
return;
}
}
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(this.readerContext, root, parent);
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}

第七步
展开parseBeanDefinitions(root, this.delegate)。这一步从文档的根元素解析文档。delegate.isDefaultNamespace(ele)这一步判断ele是不是默认命名域,这里的默认命名域为”http://www.springframework.org/schema/beans"。如果ele是默认命名域则解析ele,即parseDefaultElement(ele, delegate)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 从文档的根元素解析文档
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i &lt; nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}

第八步
展开parseDefaultElement(ele, delegate)。可以看到,我们是BEAN_ELEMENT,所以走processBeanDefinition(ele, delegate);这一步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//走这一步
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}

第九步
展开processBeanDefinition(ele, delegate)。这一步首先使用bean元素定义了BeanDefinitionHolder实例bdHolder,目前不详细解析了,BeanDefinitionHolder包含BeanDefinition名和别名,可以注册为一个内部bean的占位符。然后如果需要则修饰Bean定义。最后通过BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())注册bean定义,BeanDefinitionReaderUtils类包含了bean定义阅读接口实现时有用的工具方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 处理bean元素,解析bean定义并注册
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(&quot;Failed to register bean definition with name '&quot; +
bdHolder.getBeanName() + &quot;'&quot;, ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}

第十步
展开BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())。首先获取bean名称;然后通过registry注册bean定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 使用最初的bean factory注册bean定义
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}

第十一步
展开registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())。可以看到,这一步主要完成的工作有,bean定义校验、有旧定义是否可覆盖、添加新的bean定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, &quot;Bean name must not be empty&quot;);
Assert.notNull(beanDefinition, &quot;BeanDefinition must not be null&quot;);
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
&quot;Validation of bean definition failed&quot;, ex);
}
}
BeanDefinition oldBeanDefinition;
synchronized (this.beanDefinitionMap) {
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
&quot;Cannot register bean definition [&quot; + beanDefinition + &quot;] for bean '&quot; + beanName +
&quot;': There is already [&quot; + oldBeanDefinition + &quot;] bound.&quot;);
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info(&quot;Overriding bean definition for bean '&quot; + beanName +
&quot;': replacing [&quot; + oldBeanDefinition + &quot;] with [&quot; + beanDefinition + &quot;]&quot;);
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

到此为止bean定义的加载已经完成。但是由于代码过于复杂,没有分析很多细节以及异常,仅仅是将主要的一条线理了出来,还是远远不够的。有机会在进行深入解析。接下来会继续分析我们的demo运行。

Jerky Lu wechat
欢迎加入微信公众号